package com.specter.mvc.view.poi;

import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.specter.mvc.web.WebContext;
import com.specter.utils.BeanUtils;
import com.specter.utils.StringUtils;

/**
 * Note:利用Apache的POI进行Excel操作
 * 
 * @author Liang.Wang
 * @version 2017-04-15
 */
public class Excel {

	private Map<String, String> comments = new LinkedHashMap<>();// 所有表头字段说明
	private Map<String, String> headers = new LinkedHashMap<>();// 输出的表头说明

	public void setComment(String key, String value) {
		this.comments.put(key, value);
	}

	public void setHeader(String key, String value) {
		this.headers.put(key, value);
	}

	public void setHeaders(String[] fields) {
		for (String f : fields) {
			this.headers.put(f, comments.get(f));
		}
	}

	/**
	 * 直接数据导出
	 * 
	 * @param headers
	 * @param dataset
	 */
	public static void export(Map<String, String> headers, List<?> dataset) {
		Excel xlsx = new Excel();
		xlsx.creatWorkbook(headers, dataset);
	}

	/**
	 * 数据导出
	 * 
	 * @param headers
	 * @param dataset
	 */
	public void creatWorkbook(Map<String, String> headers, List<?> dataset) {
		WebContext.getResponse().setContentType("octets/stream");
		WebContext.getResponse().setHeader("Content-Disposition",
				"attachment;filename=" + DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + ".xls");

		XSSFWorkbook workbook = new XSSFWorkbook();
		setWorkbook(workbook, headers, dataset);

		try {
			workbook.write(WebContext.getResponse().getOutputStream());
			workbook.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void setWorkbook(Workbook wb, List<?> dataset) {
		this.setWorkbook(wb, headers, dataset);
	}

	public void setWorkbook(Workbook wb, Map<String, String> headers, List<?> dataset) {
		XSSFWorkbook workbook = (XSSFWorkbook) wb;

		XSSFSheet sheet = workbook.createSheet("sheet1");
		short width = 20, height = 25 * 20;
		sheet.setDefaultColumnWidth(width);
		sheet.setDefaultRowHeight(height);

		headers = headers == null ? this.headers : headers;// 需要导出的内容
		headers = headers.size() == 0 ? this.comments : headers;// 导出所有结果
		CellStyle hstyle = headStyle(workbook);
		CellStyle dstyle = dataStyle(workbook);

		for (int i = 0; i <= dataset.size(); i++) {
			XSSFRow row = sheet.createRow(i);
			int j = 0;
			for (Map.Entry<String, String> entry : headers.entrySet()) {
				XSSFCell cell = row.createCell(j++);
				if (i == 0) {// 设置标题
					cell.setCellStyle(hstyle);
					cell.setCellValue(Objects.toString(BeanUtils.get(headers, entry.getKey()), ""));
				} else {// 设置内容
					Object entity = dataset.get(i - 1);
					cell.setCellStyle(dstyle);
					cell.setCellValue(value(entry.getKey(), BeanUtils.get(entity, entry.getKey())));
				}
			}
		}
	}

	public CellStyle headStyle(Workbook wb) {
		XSSFWorkbook workbook = (XSSFWorkbook) wb;
		XSSFCellStyle style = workbook.createCellStyle(); // 标题样式
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setVerticalAlignment(VerticalAlignment.CENTER);

		XSSFFont font = workbook.createFont(); // 标题字体
		font.setBold(true);
		font.setFontHeightInPoints((short) 11);
		style.setFont(font);

		return style;
	}

	public CellStyle dataStyle(Workbook wb) {
		XSSFWorkbook workbook = (XSSFWorkbook) wb;

		XSSFCellStyle style = workbook.createCellStyle(); // 内容样式
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setVerticalAlignment(VerticalAlignment.CENTER);

		XSSFFont font = workbook.createFont(); // 内容字体
		font.setBold(false);
		font.setFontHeightInPoints((short) 11);
		style.setFont(font);

		return style;
	}

	private String value(String fieldName, Object fieldValue) {
		String value = "";
		if (fieldValue instanceof Date date) {
			value = DateFormatUtils.format(date, "yyyy-MM-dd");
		} else {
			value = Objects.toString(fieldValue, "");
		}

		Map<String, String> dict = this.dict(this.comments.get(fieldName));
		if (dict != null && dict.size() > 0) {
			String v = dict.get(value);
			value = StringUtils.isBlank(v) ? value : v;
		}
		return value;
	}

	private Map<String, String> dict(String comment) {
		String regex = "^\\S+\\((.*:.*(/)?)+\\)$";
		Map<String, String> dict = null;
		if (Pattern.compile(regex).matcher(comment).matches()) {
			dict = new HashMap<>();
			String[] maps = StringUtils.substringBetween(comment, "(", ")").split("/");
			for (String m : maps) {
				String[] kv = m.split(":");
				dict.put(kv[0], kv[1]);
			}
		}
		return dict;
	}
}
